package com.zzy.config;

import com.zzy.commons.DataType;
import com.zzy.commons.QueryWrapper;
import com.zzy.utils.MapperUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class BaseMapper<T> extends DBConfig{
    private String tableName;
    private Class<T> clazz;

    public BaseMapper(String tableName, Class<T> clazz) {
        this.tableName = tableName;
        this.clazz = clazz;
    }

    // insert
    public Integer insert(T t) {
        int result = -1;
        String insertSql = "insert into "+tableName+" values";
        StringBuffer buffer = new StringBuffer(insertSql);
        buffer.append("(");
        Class<?> aClass = t.getClass();
        Field[] fields = aClass.getDeclaredFields();

        try {
            for (Field field : fields) {
                buffer = MapperUtils.setFieldValue(buffer,field,t);
                buffer.append(",");
            }
            buffer.deleteCharAt(buffer.length()-1);
            buffer.append(")");
            String sql = buffer.toString();
            Statement st = getStmt();
            result = st.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    // update
    public Integer update(T t) {
        int result = -1;
        String updateSql = "update "+tableName+" set ";
        StringBuffer buffer = new StringBuffer(updateSql);
        Class<?> aClass = t.getClass();
        Field[] fields = aClass.getDeclaredFields();

        try {
            for (Field field : fields) {
                buffer = MapperUtils.setFiledNameAndValue(buffer, field, t);
                buffer.append(",");
            }
            buffer.deleteCharAt(buffer.length()-1);
            for (Field field : fields) {
                buffer.append(" where ");
                if (MapperUtils.isPrimaryKey(field)) {
                    buffer = MapperUtils.setFiledNameAndValue(buffer,field,t);
                    break;
                }
            }
            String sql = buffer.toString();
            Statement st = getStmt();
            result = st.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    // delete
    public Integer deleteById(Integer id) {
        int result = -1;
        String deleteSql = "delete from "+tableName+" where ";
        StringBuffer buffer = new StringBuffer(deleteSql);
        Field[] fields = clazz.getDeclaredFields();
        try {
            Object o = clazz.newInstance();
            for (Field field : fields) {
                if (MapperUtils.isPrimaryKey(field)) {
                    buffer = MapperUtils.setFiledNameAndValue(buffer,field,o);
                    buffer.append(id);
                    break;
                }
            }
            String sql = buffer.toString();
            Statement st = getStmt();
            result = st.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    // selectById
    public Object selectById(Integer id) {
        Object result = null;
        String selectByIdSql = "select * from "+tableName+" where ";
        Field[] fields = clazz.getDeclaredFields();
        Method[] methods = clazz.getDeclaredMethods();

        StringBuffer sqlBuffer = new StringBuffer(selectByIdSql);
        StringBuffer buffer = new StringBuffer("set");

        try {
            result = clazz.newInstance();
            for (Field field : fields) {
                if (MapperUtils.isPrimaryKey(field)) {
                    sqlBuffer = MapperUtils.setFiledNameAndValue(sqlBuffer,field,result);
                    sqlBuffer.append(id);
                    break;
                }
            }
            String sql = sqlBuffer.toString();
            Statement st = getStmt();
            ResultSet resultSet = st.executeQuery(sql);
            if (resultSet.next()){
                for (Field field : fields) {
                    buffer.append(field.getName().substring(0,1).toUpperCase());
                    buffer.append(field.getName().substring(1));
                    for (Method method : methods) {
                        if (buffer.toString().equals(method.getName())){
                            Object value = MapperUtils.getValue(field, resultSet);
                            if (value != null){
                                method.invoke(result,value);
                                break;
                            }
                        }
                    }
                    buffer = new StringBuffer("set");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    // selectAll
    public List<Object> selectAll(QueryWrapper<T> handler) {
        List<Object> list = new ArrayList<>();
        Object result = null;
        try {
            result = clazz.newInstance();
            String selectListSql = "select * from "+tableName+" where ";
            StringBuffer sqlBuffer = new StringBuffer(selectListSql);

            Field[] fields = clazz.getDeclaredFields();
            Method[] methods = clazz.getDeclaredMethods();
            for (String s : handler.keySet()) {
                for (Field field: fields){
                    if (s.equals(field.getName())){
                        if (field.getGenericType().getTypeName().equals(DataType.stringType) || field.getGenericType().getTypeName().equals(DataType.dateType)){
                            sqlBuffer = MapperUtils.setFiledNameAndValue(sqlBuffer,field,result);
                            sqlBuffer.append("'");
                            sqlBuffer.append(handler.get(s));
                            sqlBuffer.append("'");
                            sqlBuffer.append(" and ");
                        }else {
                            sqlBuffer = MapperUtils.setFiledNameAndValue(sqlBuffer,field,result);
                            sqlBuffer.append(handler.get(s));
                            sqlBuffer.append(" and ");
                        }

                    }
                }
            }
            sqlBuffer.delete(sqlBuffer.length()-5,sqlBuffer.length()-1);
            String sql = sqlBuffer.toString();
            StringBuffer buffer = new StringBuffer("set");
            Statement statement = getStmt();
            ResultSet resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
                Object obj = clazz.newInstance();
                for (Field field : fields) {
                    buffer.append(field.getName().substring(0,1).toUpperCase());
                    buffer.append(field.getName().substring(1));
                    for (Method method : methods) {
                        if (buffer.toString().equals(method.getName())){
                            Object value = MapperUtils.getValue(field, resultSet);
                            if (value != null){
                                method.invoke(obj,value);
                                break;
                            }
                        }
                    }
                    buffer = new StringBuffer("set");
                }
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    // selectOne
    public Object selectOne(QueryWrapper<T> wrapper) {
        Object result = null;
        try {
            result = clazz.newInstance();;
            String selectOneSql = "select * from "+tableName+" where ";
            StringBuffer sqlBuffer = new StringBuffer(selectOneSql);

            Field[] fields = clazz.getDeclaredFields();
            Method[] methods = clazz.getDeclaredMethods();
            for (String s : wrapper.keySet()) {
                for (Field field: fields){
                    if (s.equals(field.getName())){
                        if (field.getGenericType().getTypeName().equals(DataType.stringType) || field.getGenericType().getTypeName().equals(DataType.dateType)){
                            sqlBuffer = MapperUtils.setFiledNameAndValue(sqlBuffer,field,result);
                            sqlBuffer.append("'");
                            sqlBuffer.append(wrapper.get(s));
                            sqlBuffer.append("'");
                            sqlBuffer.append(" and ");
                        }else {
                            sqlBuffer = MapperUtils.setFiledNameAndValue(sqlBuffer,field,result);
                            sqlBuffer.append(wrapper.get(s));
                            sqlBuffer.append(" and ");
                        }

                    }
                }
            }
            sqlBuffer.delete(sqlBuffer.length()-5,sqlBuffer.length()-1);
            String sql = sqlBuffer.toString();

            StringBuffer buffer = new StringBuffer("set");

            Statement statement = getStmt();
            ResultSet resultSet = statement.executeQuery(sql);
            if (resultSet.next()){
                for (Field field : fields) {
                    buffer.append(field.getName().substring(0,1).toUpperCase());
                    buffer.append(field.getName().substring(1));
                    for (Method method : methods) {
                        if (buffer.toString().equals(method.getName())){
                            Object value = MapperUtils.getValue(field, resultSet);
                            if (value != null){
                                method.invoke(result,value);
                                break;
                            }
                        }
                    }
                    buffer = new StringBuffer("set");
                }
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
        return result;
    }

    // selectCount


}
